const OTA_MEI_TUAN = "meiTuan";
const _mtsiApiReg = /\/api\/v1\/ebooking\/*/;
const BASIC_STORAGE_NAME = 'ebooking.basic.info.v2';
const NEW_WORKBENCH_POI = 'ebooking:new-workbench:poi'
const ME_BASIC_INFO_CACHE_KEY = 'ME_BASIC_INFO_CACHE_KEY'
const ME_SELECTED_POI_INFO_CACHE_KEY = 'ME_SELECTED_POI_INFO_CACHE_KEY'
let csecversion = '3.0.0'

if (window.location.href.includes('me.meituan.com')) {
  csecversion = '3.1.0'
}

const changeMeiTuanUrl = function (url) {
  let userId = window.userId;
  let partnerId = window.partnerId;
  let basicinfo = window.basicinfo;
  if (!_mtsiApiReg.test(url)){
    return url;
  }

  if (!userId || !partnerId || !basicinfo) {
    const _prefechLsStr = localStorage.getItem(BASIC_STORAGE_NAME)
    const poiStr = localStorage.getItem(NEW_WORKBENCH_POI)

    if (_prefechLsStr) {
      try {
        const _prefechLs = JSON.parse(_prefechLsStr)
        userId = _prefechLs.value.userId;
        partnerId = _prefechLs.value.partnerId;
        basicinfo = _prefechLs.value.basicinfo || {};
        window.partnerId = partnerId
        window.userId = userId
      } catch (e) {}
    } else {
      const cacheKeyStr = localStorage.getItem(ME_BASIC_INFO_CACHE_KEY)

      if (cacheKeyStr) {
        try {
          const cacheKey = JSON.parse(cacheKeyStr)
          const obj = cacheKey.value.merchantAccountInfo
          userId = obj.accountId
          partnerId = obj.partnerId
          window.partnerId = partnerId
          window.userId = userId
        } catch (e) {}
      }
    }

    if (poiStr) {
      try {
        window.poiId = JSON.parse(poiStr)?.poiId
      } catch (e) {}
    }

    if (!window.poiId) {
      const poiCacheKeyStr = localStorage.getItem(ME_SELECTED_POI_INFO_CACHE_KEY)

      if (poiCacheKeyStr) {
        try {
          const poiCacheKey = JSON.parse(poiCacheKeyStr)
          window.poiId = poiCacheKey.value.poiId
        } catch (e) {}
      }
    }

    if (!window.poiId) {
      window.poiId = sessionStorage.getItem('poiId')
    }

    if (!window.partnerId || !window.userId) {
      let globalStorage = localStorage.getItem('globalStorage')

      if (globalStorage) {
        try {
          globalStorage = JSON.parse(globalStorage)
          const keys = Object.keys(globalStorage)

          if (keys?.length) {
            let key = keys[0]
            let index = key.indexOf(',')

            if (index > -1) {
              key = key.substring(index + 5)
              const obj = JSON.parse(key.trim())

              if (obj.partnerId) {
                partnerId = obj.partnerId
                window.partnerId = partnerId
              }

              if (obj.bizAccountId) {
                userId = obj.bizAccountId
                window.userId = userId
              }
            }
          }
        } catch (e) {
          console.error(e)
        }
      }
    }
  }

  if (!partnerId || !window.poiId) {
    return null
  }

  let mtsiParamsStr = '_mtsi_eb_u=' + (userId || 'unknown')
      + '&_mtsi_eb_p=' + (partnerId || 'unknown')
      + '&optimus_uuid=' + (partnerId || '')
      + '&optimus_risk_level=71'
      + '&optimus_code=10'
      + '&login_type=' + (basicinfo && basicinfo.bdId ? 'no_password' : 'unknown');
  let hashIndex = url.indexOf('?');
  let str = ''
  if (hashIndex !== -1) {
    if (url.substring(hashIndex + 1)) {
      str = '&' + mtsiParamsStr;
    } else {
      str = mtsiParamsStr;
    }
  } else {
    str = '?' + mtsiParamsStr;
  }

  return url + str;
};

async function redirectTarget(domain, targetUrl) {
  if (
    window.location.href.includes(domain) &&
    window.location.href !== targetUrl
  ) {
    window.location.href = targetUrl;
    await sleep(3000);
  }
}

const storePoiId = (data) => {
  if (data?.poiList) {
    window.poiId = data.poiList[0].poiId
    sessionStorage.setItem('poiId', window.poiId)
  }
}

async function requestMeiTuanPoi() {
  try {
    if (localStorage.getItem(NEW_WORKBENCH_POI) || sessionStorage.getItem('poiId')) {
      return
    }

    let url = "https://eb.meituan.com/api/v1/ebooking/common/pois";
    url = changeMeiTuanUrl(url)

    if (!url) {
      return
    }

    url += `&offset=1&pageSize=20&source=9&useAuth=true&authName=&yodaReady=h5&csecplatform=4&csecversion=${csecversion}`

    return window.H5guard.sign({
      url
    }).then(async res => {
      const {headers} = res

      if (window.location.host === MEI_TUAN_DOMAIN_3) {
        chrome.runtime.sendMessage({
          msgType: 'forward',
          ota: OTA_MEI_TUAN,
          bizType: 'pois',
          data: {
            headers: {
              ...headers,
              cookie: document.cookie
            },
            url
          }
        })
        return
      }

      const {data} = await fetch(url, {
        headers: {
          ...headers,
          cookie: document.cookie
        },
        method: 'GET'
      }).then(res => {
        return res.json()
      })

      storePoiId(data)
    })
  } catch (e) {
    console.error(e)
  }
}

/**
 * 待入住订单需要连续发送全部待入住和今日待入住请求，因为凌晨的订单是在今日待入住里
 * @param msgType
 * @param index
 * @param isTodayAwait 是否今日待入住
 * @returns {Promise<void>}
 */
async function requestMeiTuan(msgType, index = 0, isTodayAwait = false) {
  try {
    if (![PULL_MEI_TUAN_AWAIT_CHECKIN, PULL_MEI_TUAN_CANCELED].includes(msgType)) {
      return 0
    }

    await requestMeiTuanPoi()
    const timeDiff = 30 * 24 * 3600 * 1000
    const now = new Date()
    let startTime
    let endTime
    let orderStatus = ''
    let filter = ''
    let offset = index * 10
    const limit = 10
    let sortType

    if (msgType === PULL_MEI_TUAN_AWAIT_CHECKIN) {
      startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0).getTime()
      if (isTodayAwait) {
        endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59).getTime()
        filter = 'READY_TO_CHECKIN'
        sortType = 2
      } else {
        endTime = Date.now() + timeDiff
        filter = 'ALL_READY_TO_CHECK_IN'
        sortType = 1
      }
    } else {
      startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0).getTime() - timeDiff
      endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59).getTime()
      orderStatus = 'CANCELED'
      filter = 'ALL'
    }

    let host = window.location.host

    if (host !== MEI_TUAN_DOMAIN_2) {
      host = MEI_TUAN_DOMAIN
    }

    let url = `https://${host}/api/v1/ebooking/orders`
    url = changeMeiTuanUrl(url)

    if (!url) {
      return
    }

    url += `&partnerId=${window.partnerId}&poiId=${window.poiId}&startTime=${startTime}&endTime=${endTime}&filter=${filter}&invoiceMark=0&offset=${offset}&memberMark=0&limit=${limit}&checkInName=&orderStatus=${orderStatus}&hkbMark=0&orderType=4,7&phone=&roomIds=`

    if (msgType === PULL_MEI_TUAN_AWAIT_CHECKIN) {
      url += `&searchTimeType=1&sortField=1&sortType=${sortType}&zlPois=&checkInStatus=2`
    } else {
      url += `&searchTimeType=2&sortField=2&sortType=2&zlPois=`
    }

    url += `&bizTag=0&yodaReady=h5&csecplatform=4&csecversion=${csecversion}`

    const res = await window.H5guard.sign({
      url
    })

    if (window.location.host === MEI_TUAN_DOMAIN_3) {
      chrome.runtime.sendMessage({
        msgType: 'forward',
        ota: OTA_MEI_TUAN,
        bizType: 'orders',
        data: {
          headers: {
            ...res.headers,
            cookie: document.cookie
          },
          url
        }
      })
      return 0
    }

    const {data} = await fetch(url, {
      method: 'GET',
      headers: {
        ...res.headers,
        cookie: document.cookie
      }
    }).then(res => {
      return res.json()
    })

    await walkMeiTuanOrders(data)
  } catch (e) {
    console.error(e)
  }
}

async function walkMeiTuanOrders(data) {
  try {
    if (!data) {
      return
    }

    const results = data.results


    if (!results?.length) {
      return
    }

    let host = window.location.host

    if (host !== MEI_TUAN_DOMAIN_2) {
      host = MEI_TUAN_DOMAIN
    }

    for (const result of results) {
      url = `https://${host}/api/v1/ebooking/orders/${result.orderId}`
      url += `?userId=${window.userId}&yodaReady=h5&csecplatform=4&csecversion=${csecversion}`
      url = changeMeiTuanUrl(url)

      if (!url) {
        return
      }



      window.H5guard.sign({
        url
      }).then(async res => {
        const {headers} = res

        if (window.location.host === MEI_TUAN_DOMAIN_3) {
          chrome.runtime.sendMessage({
            msgType: 'forward',
            ota: OTA_MEI_TUAN,
            bizType: 'detail',
            data: {
              headers: {
                ...headers,
                cookie: document.cookie
              },
              url
            }
          })
          return
        }

        const {data} = await fetch(url, {
          headers,
          method: 'GET'
        }).then(res => {
          return res.json()
        })

        if (data) {
          chrome.runtime.sendMessage({
            msgType: 'response',
            ota: OTA_MEI_TUAN,
            data: [data]
          })
        }
      })

      await sleep(3000 + Math.random() * 2000)
    }

    return results?.length
  } catch (e) {
    console.error(e)
  }
}

async function handleMeiTuan(msgType, isTodayAwait = false) {
  for (let i = 0; i < 3; i++) {
    const count = await requestMeiTuan(msgType, i, isTodayAwait)

    if (count < 10) {
      break
    }
  }
}

async function handleCtrip(message) {
  window.postMessage(message)
}

async function pullData(msgType, pageCount = 1) {
  try {
    for (let i = 0; i < pageCount; i++) {
      let data = {};

      if (msgType === PMS_PULL_MEI_TUAN_CANCELED) {
        data = {
          msgType: PULL_MEI_TUAN_CANCELED,
          data: {
            pageIdx: i,
          },
        };
      }

      if (msgType === PMS_PULL_MEI_TUAN_AWAIT_CHECKIN) {
        data = {
          msgType: PULL_MEI_TUAN_AWAIT_CHECKIN,
          data: {
            pageIdx: i,
          },
        };
      }

      if (msgType === PMS_PULL_CTRIP) {
        data = {
          msgType: PULL_CTRIP,
          data: {
            pageIdx: i + 1,
          },
        };
      }

      await chrome.runtime.sendMessage(data);
      await sleep(i === 0 ? 8000 : 3000);
    }
  } catch (e) {
    console.error(e);
  }
}

// 监听美团新订单或取消订单
async function listenMeiTuan() {
  // if (window.location.href.includes(MEI_TUAN_DOMAIN) || window.location.href.includes(MEI_TUAN_DOMAIN_2) || window.location.href.includes(MEI_TUAN_DOMAIN_3)) {
  //   if (document.title.includes('新') || document.title.includes('取消')) {
  //     await handleMeiTuan(PULL_MEI_TUAN_AWAIT_CHECKIN);
  //     await handleMeiTuan(PULL_MEI_TUAN_AWAIT_CHECKIN, true);
  //     await handleMeiTuan(PULL_MEI_TUAN_CANCELED);
  //   }
  //
  //   await sleep(5000)
  //   await listenMeiTuan()
  // }
}

// 监听携程新订单或取消订单
async function listenCtrip() {
  if (window.location.href.includes(CTRIP_DOMAIN)) {
    if (document.title.includes('未处理')) {
      await handleCtrip({
        msgType: PULL_CTRIP,
      });
    }

    await sleep(2000)
    await listenCtrip()
  }
}

function main() {
  window.addEventListener("message", async (event) => {
    try {
      const {data} = event;
      const msgType = data?.msgType;

      switch (msgType) {
        case PMS_PULL_MEI_TUAN_CANCELED:
        case PMS_PULL_MEI_TUAN_AWAIT_CHECKIN:
          await pullData(msgType, 1);
          break;
        case PMS_PULL_CTRIP:
          await pullData(msgType, 1);
          break;
        case REFRESH_ORDER_LIST: {
          if (window.location.href.includes(MEI_TUAN_DOMAIN) || window.location.href.includes(MEI_TUAN_DOMAIN_2) || window.location.href.includes(MEI_TUAN_DOMAIN_3)) {
            await handleMeiTuan(PULL_MEI_TUAN_AWAIT_CHECKIN);
            await handleMeiTuan(PULL_MEI_TUAN_AWAIT_CHECKIN, true);
          }

          if (window.location.href.includes(CTRIP_DOMAIN)) {
            await handleCtrip({
              msgType: PULL_CTRIP,
            });
          }
        }
          break;
        case "response":
          await chrome.runtime.sendMessage(data);
          break;
      }
    } catch (e) {
      console.error(e);
    }
  });

  chrome.runtime.onMessage.addListener(async (message) => {
    try {
      switch (message?.msgType) {
        case PULL_MEI_TUAN_CANCELED:
        case PULL_MEI_TUAN_AWAIT_CHECKIN:
          await handleMeiTuan(message?.msgType);

          if (message?.msgType === PULL_MEI_TUAN_AWAIT_CHECKIN) {
            await handleMeiTuan(message?.msgType, true)
          }
          break;
        case PULL_CTRIP:
          await handleCtrip(message);
          break;
        case "response":
          if (!message.data) {
            break;
          }

          await Promise.all(
            message.data?.map((t) => {
              return pushDataToPms({
                ota: message.ota,
                content: t,
              });
            })
          );
          break;
        case "forward":
          if (message.ota === OTA_MEI_TUAN) {
            if (message.bizType === 'pois') {
              storePoiId(message.data)
            }

            if (message.bizType === 'orders') {
              walkMeiTuanOrders(message.data)
            }

            if (message.bizType === 'detail') {
              pushDataToPms({
                ota: message.ota,
                content: message.data,
              })
            }
          }
          break;
      }
    } catch (e) {
      console.error(e);
    }
  });

  if (
    [MEI_TUAN_DOMAIN, MEI_TUAN_DOMAIN_2, MEI_TUAN_DOMAIN_3, CTRIP_DOMAIN, MFB_DOMAIN, XZL_DOMAIN, "localhost"].some((t) =>
      window.location.href.includes(t)
    )
  ) {
    setTimeout(() => {
      insertScript("/js/inject.js");
    }, 2000)
  }

  if ([MFB_DOMAIN, XZL_DOMAIN, "localhost"].some((t) => window.location.href.includes(t))) {
    const element = document.createElement("div");
    element.setAttribute("id", "mfb-ota-plugin");
    document.body.appendChild(element);
  }

  listenMeiTuan()
  listenCtrip()
}

try {
  insertScript("/js/common/jquery-1.9.1.min.js");
  insertScript("/js/common/ajaxHooker.js");
  insertScript("/js/common/index.js");
  insertScript("/js/ctrip/util.js");
  insertScript("/js/ctrip/index.js");
  main();
} catch (e) {
  console.error(e);
}
